﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExtendPropertyLib.WPF;
using ExtendPropertyLib;
using ExORMDesginer.Services;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
using ExORMDesginer.Models;
using System.Collections.ObjectModel;
using DatabaseSchemaReader;
using DatabaseSchemaReader.DataSchema;
using System.Collections.Specialized;
using ExORMDesginer.Plugin;
using ExORMDesginer.UserControls;
using ExORMDesginer.RadWindow.Helper;
namespace ExORMDesginer
{
    public class MainInfo : BusinessInfoBase<MainInfo>
    {
        [Import("DatabaseMeta")]
        private DatabaseMetaService isn;

        [Import(typeof(ILoger))]
        public ILoger Log { set; get; }


        public static ExtendProperty ConnectionStringProperty = RegisterProperty(v => v.ConnectionString);
        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString { set { SetValue(ConnectionStringProperty, value); } get { return (string)GetValue(ConnectionStringProperty); } }

        public static ExtendProperty TablesProperty = RegisterProperty(m => m.Tables);
        /// <summary>
        /// 物理表元数据
        /// </summary>
        public SerializableObservableCollection<DbEntity> Tables
        {
            set
            {
                SetValue(TablesProperty, value);
            }
            get
            {
                return (SerializableObservableCollection<DbEntity>)GetValue(TablesProperty);
            }
        }

        
        public static ExtendProperty DatabaseNameProperty = RegisterProperty(v => v.DatabaseName);
        /// <summary>
        /// 数据库名称
        /// </summary>
        public string DatabaseName { set { SetValue(DatabaseNameProperty, value); } get { return (string)GetValue(DatabaseNameProperty); } }
        /// <summary>
        /// 数据库结构
        /// </summary>
        public DatabaseSchema Schema { set; get; }
        
        public static ExtendProperty IsOpenProperty = RegisterProperty(v => v.IsOpen);
        /// <summary>
        /// 基于文件系统打开
        /// </summary>
        public bool IsOpen { set { SetValue(IsOpenProperty, value); } get { return (bool)GetValue(IsOpenProperty); } }
        
        public static ExtendProperty DisplayEntitysProperty = RegisterProperty(v => v.DisplayEntitys);
        /// <summary>
        /// 要在图形界面中显示的数据实体
        /// </summary>
        public SerializableObservableCollection<DbEntity> DisplayEntitys { set { SetValue(DisplayEntitysProperty, value); } get { return (SerializableObservableCollection<DbEntity>)GetValue(DisplayEntitysProperty); } }


        public static ExtendProperty FilterEntitysProperty = RegisterProperty(v => v.FilterEntitys);
        /// <summary>
        /// 过滤数据实体
        /// </summary>
        public SerializableObservableCollection<DbEntity> FilterEntitys { set { SetValue(FilterEntitysProperty, value); } get { return (SerializableObservableCollection<DbEntity>)GetValue(FilterEntitysProperty); } }
        


        public static ExtendProperty FoldersProperty = RegisterProperty(v => v.Folders);
        /// <summary>
        /// 目录
        /// </summary>
        public SerializableObservableCollection<FolderInfo> Folders { set { SetValue(FoldersProperty, value); } get { return (SerializableObservableCollection<FolderInfo>)GetValue(FoldersProperty); } }

        /// <summary>
        /// 过滤功能中，被选择显示的数据库对象名
        /// </summary>
        public List<string> SelectedItemNames { set; get; }

        
        public static ExtendProperty SQLTypeProperty = RegisterProperty(v => v.SQLType);
        /// <summary>
        /// SQL数据库类型
        /// </summary>
        public SqlType SQLType { set { SetValue(SQLTypeProperty, value); } get { return (SqlType)GetValue(SQLTypeProperty); } }

        /// <summary>
        /// 创建子文件夹
        /// </summary>
        /// <param name="parent">父文件夹</param>
        /// <param name="name">创建名称</param>
        public void CreateChildrenFolder(FolderInfo parent,string name)
        {
            FolderInfo childrenFolder = new FolderInfo();
            childrenFolder.Name = name;
            childrenFolder.InfoType = parent.InfoType;
            parent.Items.Add(childrenFolder);
            parent.FolderCollection.Add(childrenFolder);
            Folders.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }


        /// <summary>
        /// 删除子文件夹
        /// </summary>
        /// <param name="parent">父文件夹</param>
        /// <param name="childrenFolder">子文件夹</param>
        /// <returns>是否删除成功</returns>
        public bool RemoveChildrenFolder(FolderInfo parent, FolderInfo childrenFolder)
        {
            if (childrenFolder.TableCollection.Count > 0)
            {
                parent.Items.Remove(childrenFolder);
                parent.FolderCollection.Remove(childrenFolder);
                Folders.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                return true;
            }
            return false;
        }

      


        /// <summary>
        /// 得到所有表构架信息
        /// </summary>
        /// <param name="connString"></param>
        /// <returns></returns>
        public async Task GetSchemas()
        {
            Log.Write("-----------------------------正在获取表构架信息......-------------------------");
            if (string.IsNullOrEmpty(this.ConnectionString))
            {
                Log.Write("获取表构架信息错误，数据库连接为空.");
                return;
            }
            Log.Write("开始获取表构架信息,连接字符串:" + this.ConnectionString);
            DatabaseReader reader = new DatabaseReader(this.ConnectionString, SQLType);

            var schema = await TaskEx.Run<DatabaseSchema>(() =>{ 
                            return reader.ReadAll();
                         });
            this.Schema = schema;


            var vm = Parent as MainViewModel;
            vm.FilterDbSchemaViewModel.Model.Init(this.Schema,SelectedItemNames);
            vm.Window.ShowDialog(vm.FilterDbSchemaViewModel);
            var filterSchema = vm.FilterDbSchemaViewModel.Model;


            var rootFolder = new FolderInfo() { Name = "目录视图", InfoType = "Root", IsRoot = true };

            FolderInfo TableFolder = new FolderInfo() { Name = "物理模型", InfoType = "Table", IsRoot = true };
            rootFolder.FolderCollection.Add(TableFolder);
            var ViewFolder = new FolderInfo() { Name = "视图", InfoType = "View", IsRoot = true };
            rootFolder.FolderCollection.Add(ViewFolder);
            var StoredProceduresFolder = new FolderInfo() { Name = "存储过程", InfoType = "StoredProcedures", IsRoot = true };
            rootFolder.FolderCollection.Add(StoredProceduresFolder);
          
           
            FilterEntitys = new SerializableObservableCollection<DbEntity>();

            if (!this.IsOpen)
            {
                this.Folders = new SerializableObservableCollection<FolderInfo>();
                this.Folders.Add(rootFolder);
            }

            Tables = new SerializableObservableCollection<DbEntity>();

            #region Tables
          
            foreach (var table in  schema.Tables)
             {
                var dbe = new DbEntity();
                dbe.Name = table.Name;
                dbe.DbName = table.Name;
                dbe.Memo = table.Description;
                dbe.ID = Guid.NewGuid();
                dbe.EntityViewType = EntityType.Table;
                if (table.PrimaryKey != null && table.PrimaryKey.Columns.Count > 0)
                {
                    string keys = string.Join(",", table.PrimaryKey.Columns);
                    dbe.Keys = keys;
                }
                foreach (var column in table.Columns)
                {
                    var dbp = new DbProperty();
                    dbp.Name = column.Name;
                    dbp.DbName = column.Name;
                    dbp.Memo = column.Description;
                    dbp.DefaultValue = column.DefaultValue;
                    dbp.DataType = column.DbDataType;
                    dbp.DataLength = column.Length == null ? 0 : column.Length.Value;
                    dbp.DataDotLength = column.Scale == null ? 0 : column.Scale.Value;
                    dbp.PropertyType = column.DataType.GetNetType();
                    if (dbp.PropertyType != null && dbp.PropertyType.IsValueType)
                    {
                         dbp.PropertyTypeName = string.Format("{0}?",column.DataType.NetDataTypeCSharpName);
                    }
                    else
                    {
                         dbp.PropertyTypeName = column.DataType.NetDataTypeCSharpName;
                    }
                   
                    dbp.IsPrimaryKey = column.IsPrimaryKey;
                    dbp.IsIdentity = column.IsIdentity;
                    dbp.IsNull = column.Nullable;
                    dbe.Propertys.Add(dbp);
                }


                Tables.Add(dbe);
                if (filterSchema.GetSelectedNames().Contains(dbe.Name))
                {
                    FilterEntitys.Add(dbe);
                    TableFolder.TableCollection.Add(dbe);
                }
                Log.Write("获取表构架信息 -> " + dbe.DbName + " OK.");
             }
            #endregion

            #region Views

            foreach (var view in schema.Views)
             {
                 var dbe = new DbEntity();
                 dbe.Name = view.Name;
                 dbe.DbName = view.Name;
                 dbe.Memo = view.Description;
                 dbe.ID = Guid.NewGuid();
                 dbe.EntityViewType = EntityType.View;
                 dbe.SQL = view.Sql;
                 if (view.PrimaryKey != null && view.PrimaryKey.Columns.Count > 0)
                 {
                     string keys = string.Join(",", view.PrimaryKey.Columns);
                     dbe.Keys = keys;
                 }
                 foreach (var column in view.Columns)
                 {
                     var dbp = new DbProperty();
                     dbp.Name = column.Name;
                     dbp.DbName = column.Name;
                     dbp.Memo = column.Description;
                     dbp.DefaultValue = column.DefaultValue;
                     dbp.DataType = column.DbDataType;
                     dbp.DataLength = column.Length == null ? 0 : column.Length.Value;
                     dbp.DataDotLength = column.Scale == null ? 0 : column.Scale.Value;
                     dbp.PropertyType = column.DataType.GetNetType();
                     if (dbp.PropertyType != null && dbp.PropertyType.IsValueType)
                     {
                         dbp.PropertyTypeName = string.Format("{0}?", column.DataType.NetDataTypeCSharpName);
                     }
                     else
                     {
                         dbp.PropertyTypeName = column.DataType.NetDataTypeCSharpName;
                     }
                     dbp.IsPrimaryKey = column.IsPrimaryKey;
                     dbp.IsIdentity = column.IsIdentity;
                     dbp.IsNull = column.Nullable;
                     dbe.Propertys.Add(dbp);
                 }

                 Tables.Add(dbe);
                 if (filterSchema.GetSelectedNames().Contains(dbe.Name))
                 {
                     FilterEntitys.Add(dbe);
                     ViewFolder.TableCollection.Add(dbe);
                 }
                 Log.Write("获取视图构架信息 -> " + dbe.DbName + " OK.");
                 
             }
             #endregion

            #region StoredProcedures
            foreach (var procedure in schema.StoredProcedures)
            {
                var dbe = new DbEntity();
                dbe.Name = procedure.Name;
                dbe.DbName = procedure.Name;
                dbe.ID = Guid.NewGuid();
                dbe.EntityViewType = EntityType.StoredProcedure;
                dbe.SQL = procedure.Sql;
                foreach (var column in procedure.Arguments)
                {
                    var dbp = new DbProperty();
                    dbp.Name = column.Name;
                    dbp.DbName = column.Name;
                    dbp.DataType = column.DatabaseDataType;
                    dbp.DataLength = column.Length == null ? 0 : column.Length.Value;
                    dbp.DataDotLength = column.Scale == null ? 0 : column.Scale.Value;
                    dbp.PropertyType = column.DataType.GetNetType();
                    if (dbp.PropertyType != null && dbp.PropertyType.IsValueType)
                    {
                        dbp.PropertyTypeName = string.Format("{0}?", column.DataType.NetDataTypeCSharpName);
                    }
                    else
                    {
                        dbp.PropertyTypeName = column.DataType.NetDataTypeCSharpName;
                    }
                    dbp.IsOut = !column.In;
                    
                    dbe.Propertys.Add(dbp);
                }

                Tables.Add(dbe);
                if (filterSchema.GetSelectedNames().Contains(dbe.Name))
                {
                    FilterEntitys.Add(dbe);
                    StoredProceduresFolder.TableCollection.Add(dbe);
                }
                Log.Write("获取存储过程构架信息 -> " + dbe.DbName + " OK.");
            }
            #endregion
            this.SelectedItemNames = filterSchema.GetSelectedNames();
         
            isn.Schema = schema;
            isn.TableMetas = Tables;
            isn.SQLType = SQLType;
            isn.ConnectionString = ConnectionString;
            isn.Process(Tables.ToDictionary(k => k.Name));
            ServiceManager.GetService(isn.GetType(), isn);

            MasterHost.Instance.Tables = FilterEntitys.ToList();
            IsOpen = true;
            Log.Write("----------------------------获取表构架信息完成！-----------------------------");
        }
      

    
    }
}
